package edu.whu.tao.util;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.io.IOUtils;

/**
 * 
 * <P>http工具包</P>
 * @author 陶焕(13294175866)
 * @date 2016年4月15日 下午3:29:46
 */
public class HttpUtils {

	private byte[] result;

	private boolean isSuccess = false;

	public static int connectTimeout = 20 * 1000;

	public static int readTimeout = 60 * 1000;

	public static String DEFAULT_CHARSET = "UTF-8";
	
	public static final String METHOD_GET = "GET";
	
	public static final String METHOD_POST = "POST";
	
	// public static int timeout = 60*1000;

	private HttpUtils() {

	}

	public boolean isSuccess() {
		return isSuccess;
	}
	
	/**
	 * @param urlPath
	 *            map参数
	 * @param paras
	 * @return
	 */
	public static String sendPost(String urlPath, Map<String, String> paras) {
		try {
			String temp = "";
			Iterator<Entry<String, String>> iterator = paras.entrySet()
					.iterator();
			while (iterator.hasNext()) {
				Map.Entry<String, String> entry = iterator.next();
				String key = entry.getKey();
				String value = entry.getValue();
				temp += "&" + key + "=" + URLEncoder.encode(value, "UTF-8");
			}

			temp = temp.substring(1);
			return sendPost(urlPath, temp,false);
		} catch (Exception e) {

		}
		return null;
	}

	/**
	 * 向指定URL发送POST方法的请求
	 * 
	 * @param url
	 *            发送请求的URL
	 * @param param
	 *            请求参数，请求参数应该是name1=value1&name2=value2的形式。
	 * @return URL所代表远程资源的响应
	 */

	public static String sendPost(String url, String param, boolean isGet) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();

			conn.setConnectTimeout(connectTimeout);
			conn.setReadTimeout(readTimeout);
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent",
					"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; android smartcity)");

			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			if(isGet){
				conn.setRequestMethod(METHOD_GET); // GET方式
			}else {
				conn.setRequestMethod(METHOD_POST); // POST方式
			}
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(param);
			// flush 输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(
					new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			IOUtils.closeQuietly(out);
			IOUtils.closeQuietly(in);
		}
		return result;
	}

	
	public static HttpUtils post(String actionUrl, Map<String, Object> params) {
		return post(actionUrl, params,null);
	}
	
	// 上传代码，第一个参数，为要使用的URL，第二个参数，为表单内容，第三个参数为要上传的文件，可以上传多个文件，这根据需要页定
	public static HttpUtils post(String actionUrl, Map<String, Object> params,
			Map<String, File> files) {
		//String result = null;
		//CommonResult<HttpUtils> result = new CommonResult<HttpUtils>(CommonResult.successCode);
		HttpUtils httpUtils = new HttpUtils();
		String BOUNDARY = java.util.UUID.randomUUID().toString();
		String PREFIX = "--", LINEND = "\r\n";
		String MULTIPART_FROM_DATA = "multipart/form-data";
		String CHARSET = "UTF-8";
		DataOutputStream out = null;
//		BufferedReader in = null;
		BufferedInputStream in = null;
		try {
			URL uri = new URL(actionUrl);
			HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
			conn.setReadTimeout(20 * 1000);
			conn.setConnectTimeout(10000);
			conn.setDoInput(true);// 允许输入
			conn.setDoOutput(true);// 允许输出
			conn.setUseCaches(false);
			conn.setRequestMethod("POST"); // Post方式
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "keep-alive");
			conn.setRequestProperty("user-agent",
					"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; android smartcity)");
			conn.setRequestProperty("Charsert", "UTF-8");
			if (files != null) {
				conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA
						+ ";boundary=" + BOUNDARY);
			}
			// 首先组拼文本类型的参数
			out = new DataOutputStream(conn.getOutputStream());
			StringBuilder sb = new StringBuilder();
			if (params != null) {
				//没有文件参数时使用拼接来构造参数
				if(files == null ||files.isEmpty()){
					boolean hasParam = false;
					for (Map.Entry<String, Object> entry : params.entrySet()) {
						hasParam = true;
						String key = entry.getKey();
						String value = String.valueOf(entry.getValue());
						sb.append("&" + key + "=" + value);
					}
					if(hasParam){
						sb.deleteCharAt(0);
					}
				}else {
					for (Map.Entry<String, Object> entry : params.entrySet()) {
						sb.append(PREFIX);
						sb.append(BOUNDARY);
						sb.append(LINEND);
						sb.append("Content-Disposition: form-data; name=\""
								+ entry.getKey() + "\"" + LINEND);
						sb.append("Content-Type: text/plain; charset=" + CHARSET
								+ LINEND);
						sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
						sb.append(LINEND);
						sb.append(entry.getValue());
						sb.append(LINEND);
					}
				}
				
				String ourParam = sb.toString();
				System.out.println(ourParam);
				byte[] outByte = ourParam.getBytes(CHARSET);
				out.write(outByte);
			}
			// 发送文件数据
			if (files != null && !files.isEmpty()){
				for (Map.Entry<String, File> fileMap : files.entrySet()) {
					File file = fileMap.getValue();
					String fileName = file.getName();
					StringBuilder sb1 = new StringBuilder();
					sb1.append(PREFIX);
					sb1.append(BOUNDARY);
					sb1.append(LINEND);
					sb1.append("Content-Disposition: form-data; name=\""
							+ fileMap.getKey() + "\"; filename=\"" + fileName
							+ "\"" + LINEND);
					sb1.append("Content-Type: multipart/form-data; charset="
							+ CHARSET + LINEND);
					sb1.append(LINEND);
					String ourParam = sb1.toString();
					System.out.println(ourParam);
					byte[] outByte = ourParam.getBytes(CHARSET);
					out.write(outByte);
					InputStream is = new FileInputStream(fileMap.getValue());
					byte[] buffer = new byte[1024];
					int len = 0;
					while ((len = is.read(buffer)) != -1) {
						out.write(buffer, 0, len);
					}
					is.close();
					System.out.println(LINEND);
					
					out.write(LINEND.getBytes(CHARSET));
				}
				// 请求结束标志
				System.out.println(PREFIX + BOUNDARY + PREFIX + LINEND);
				byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes(CHARSET);
				out.write(end_data);
			}
			out.flush();
			// 得到响应码
			int code = conn.getResponseCode();
			boolean success = code == 200;
			
			in = new BufferedInputStream(conn.getInputStream());
//			byte[] buffer = new byte[4096];
//			ByteArrayOutputStream output = new ByteArrayOutputStream();
//			for(int n = 0; -1 != (n = in.read(buffer));)
//	        {
//	            output.write(buffer, 0, n);
//	        }
			httpUtils.result = IOUtils.toByteArray(in);
//			httpUtils.result = output.toByteArray();
			if (success) {
				httpUtils.isSuccess = true;
			} else {
				httpUtils.isSuccess = false;
			}
			conn.disconnect();
		} catch (Exception e) {
			e.printStackTrace();
			httpUtils.isSuccess = false;

		}
		// 使用finally块来关闭输出流、输入流
		finally {
			IOUtils.closeQuietly(out);
			IOUtils.closeQuietly(in);
		}
		return httpUtils;

	}

	
	public byte[] renderToBytes() {
		return result;
	}

	public String renderToText(String charset) {
		if (result == null) {
			return null;
		}
		String strResult = null;
		try {
			strResult = new String(result, charset);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return strResult;

	}

	public String renderToText() {
		return renderToText(DEFAULT_CHARSET);

	}
	
}
